package cn.ztydata.teachingsystem.heaven.service;

import cn.ztydata.teachingsystem.exception.ServiceException;
import cn.ztydata.teachingsystem.heaven.common.WebContext;
import cn.ztydata.teachingsystem.heaven.dao.KpDao;
import cn.ztydata.teachingsystem.heaven.dao.redis.*;
import cn.ztydata.teachingsystem.heaven.entity.KnowledgePoint;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;

/**
 * 知识点服务类
 * Created by chenxin on 2014/12/8.
 */
@Service
public class KpService extends BaseService {
    @Autowired
    private KpDao kpDao;
    @Autowired
    private CourseKpDao courseKpDao;
    @Autowired
    private ChapterKpDao chapterKpDao;
    @Autowired
    private ResourceKpDao resourceKpDao;
    @Autowired
    private KpCourseDao kpCourseDao;
    @Autowired
    private KpChapterDao kpChapterDao;
    @Autowired
    private KpResourceDao kpResourceDao;
    @Autowired
    private KpExerciseDao kpExerciseDao;

    @Autowired
    private TeacherTeamService teacherTeamService;
    @Autowired
    private ChapterService chapterService;

    @Autowired
    private WebContext webContext;

    /**
     * 新增知识点
     * @param kp 知识点实体
     *
     * @author fanruiping
     * @since 2014-12-24
     */
    public void addKp(KnowledgePoint kp){
        if (!kpDao.isExist(kp)){
            log.debug("判断根据名称获取知识点:!kpDao.isExist(kp)");
            if(!kpDao.save(kp)){
                log.debug("知识点数据保存失败:!kpDao.save(kp)");
                log.error("知识点数据保存失败");

                throw new ServiceException("知识点数据保存失败");
            }
        }
    }

    /**
     * 新增课程知识点
     * @param kp 知识点
     *
     * @author cx
     * @since 2014-12-08
     */
    @Transactional
    public void saveCourseKp(KnowledgePoint kp) {
        //判断用户是否在课程的教师团队
        teacherTeamService.isMemeber(kp.getCourseId());

        //保存知识点
        addKp(kp);

        //保存课程-知识点的关系
        Boolean end = courseKpDao.saveKp(kp.getCourseId(), kp.getId());
        if (end == null || !end) {
            log.debug("保存课程-知识点关系失败:end == null || !end");
            log.warn("保存课程-知识点关系失败", end);
            throw new ServiceException();
        }
    }

    /**
     * 新增章节知识点
     *
     * @author chenxin
     * @since 2014/12/16
     */
    @Transactional
    public void saveChapterKp(KnowledgePoint kp) {
        //判断节点是否可操作
        chapterService.checkNode(kp.getNodeId(), kp.getCourseId());

        //保存知识点
        addKp(kp);

        //新增课程-知识点的关系
        Boolean courseEnd = courseKpDao.saveKp(kp.getCourseId(), kp.getId());
        if (courseEnd == null || !courseEnd) {
            log.debug("保存课程-知识点关系失败:courseEnd == null || !courseEnd");
            log.warn("保存课程-知识点关系失败", courseEnd);
            throw new ServiceException();
        }

        //新增章节-知识点的关系
        Boolean chapterEnd = chapterKpDao.saveKp(kp.getNodeId(), kp.getId());
        if (chapterEnd == null || !chapterEnd) {
            log.debug("保存章节-知识点关系失败:chapterEnd == null || !chapterEnd");
            log.warn("保存章节-知识点关系失败", chapterEnd);
            throw new ServiceException();
        }
    }

    /**
     * 删除课程与知识点的关系
     * @param kpId 知识点ID
     * @param courseId 课程ID
     *
     * @author cx
     * @since 2014-12-09
     */
    public void deleteCourseKp(final long kpId, final long courseId) {
        //判断用户是否在课程的教师团队
        teacherTeamService.isMemeber(courseId);

        //删除课程与知识点的关系
        Boolean result = courseKpDao.deleteKp(kpId, courseId);
        if (result == null || !result) {
            log.debug("删除课程知识点关系失败:result == null || !result");
            log.warn("删除课程知识点关系失败", result);
            throw new ServiceException();
        }
    }

    /**
     * 删除章节与知识点的关系
     *
     * @author chenxin
     * @since 2014/12/16
     */
    public void deleteChapterKp(final long kpId, final long nodeId) {
        //判断节点是否可操作
        chapterService.checkNode(nodeId);

        //删除章节与知识点的关系
        Boolean result = chapterKpDao.deleteKp(kpId, nodeId);
        if (result == null || !result) {
            log.debug("删除章节知识点关系失败:result == null || !result");
            log.warn("删除章节知识点关系失败", result);
            throw new ServiceException();
        }
    }

    /**
     * 获取指定课程的知识点
     * @param courseId 课程ID
     * @return List
     *
     * @author cx
     * @since 2014-12-09
     */
    public List<KnowledgePoint> getKpsForCourse(final long courseId) {
        //获取课程的知识点ID集合
        Set<Long> kpIdSet = courseKpDao.getKpIds(courseId);
        if (kpIdSet.isEmpty()) {
            log.debug("获取课程的知识点ID集合:kpIdSet.isEmpty()");
            return Lists.newArrayList();
        }

        //获取知识点信息
        log.debug("获取知识点信息");
        return kpDao.getAll(kpIdSet);
    }

    /**
     * 获取指定章节的知识点
     * @param nodeId 节点ID
     * @return List
     *
     * @author cx
     * @since 2014-12-16
     */
    public List<KnowledgePoint> getKpsForChapter(final long nodeId) {
        //获取章节的知识点ID集合
        Set<Long> kpIdSet = chapterKpDao.getKpIds(nodeId);
        if (kpIdSet.isEmpty()) {
            log.debug("获取章节的知识点ID集合:kpIdSet.isEmpty()");
            return Lists.newArrayList();
        }

        //获取知识点信息
        log.debug("获取指定章节的知识点");
        return kpDao.getAll(kpIdSet);
    }

    /**
     * 搜索知识点
     * @param keyword 搜索关键字
     * @return List
     *
     * @author cx
     * @since 2014-12-09
     */
    public List<KnowledgePoint> searchKps(final String keyword, final int top) {
        log.debug("搜索知识点");
        return kpDao.getKpsBySearch(keyword, top);
    }

    /**
     * 获取资源的知识点
     * @param resId 资源ID
     * @return List
     *
     * @author chenxin
     * @since 2015/2/9
     */
    @Cacheable(value = "teachingSystem:cache:kp", key = "'forRes:'.concat(#resId)")
    public List<KnowledgePoint> getKpsForRes(final long resId) {
        //获取资源绑定的知识点ID
        Set<Long> kpIds = resourceKpDao.getKpIds(resId);

        log.debug("获取资源的知识点");
        //获取知识点
        return kpDao.getAll(kpIds);
    }

    /**
     * 删除知识点
     * @param kpId 知识点ID
     *
     * @author chenxin
     * @since 2015/2/6
     */
    public void deleteKp(final long kpId){
        //若删除的知识点未被引用
        if (!kpCourseDao.isUsed(kpId) && !kpChapterDao.isUsed(kpId) && !kpResourceDao.isUsed(kpId) && !kpExerciseDao.isUsed(kpId)) {
            log.debug("知识点未被引用:!kpCourseDao.isUsed(kpId) && !kpChapterDao.isUsed(kpId) && !kpResourceDao.isUsed(kpId) && !kpExerciseDao.isUsed(kpId)");

            kpDao.delete(kpId);
        }
    }

    /**
     * 根据ID获取知识点集合
     * @param
     * @return List
     * @author lyj
     * @since 2015-2-4
     */
    public List<KnowledgePoint> getAll(List<Long> knowledgeIds){
        log.debug("根据ID获取知识点集合");
        return kpDao.getAll(knowledgeIds);
    }
}
